package com.nidu.demo.tenant.executor.command;

import com.alibaba.cola.dto.SingleResponse;
import com.nidu.demo.common.constants.Constants;
import com.nidu.demo.common.enums.DataScopeEnum;
import com.nidu.demo.common.enums.RoleCodeEnum;
import com.nidu.demo.common.enums.RoleTypeEnum;
import com.nidu.demo.role.gateway.RoleGateway;
import com.nidu.demo.role.gateway.RoleMenuGateway;
import com.nidu.demo.role.model.Role;
import com.nidu.demo.tenant.ability.TenantDomainService;
import com.nidu.demo.tenant.ability.TenantPackageDomainService;
import com.nidu.demo.tenant.convertor.TenantConvertor;
import com.nidu.demo.tenant.dto.TenantAddCmd;
import com.nidu.demo.tenant.dto.TenantCO;
import com.nidu.demo.tenant.gateway.TenantGateway;
import com.nidu.demo.tenant.model.Tenant;
import com.nidu.demo.tenant.model.TenantPackage;
import com.nidu.demo.tenant.util.TenantUtils;
import com.nidu.demo.user.gateway.UserGateway;
import com.nidu.demo.user.gateway.UserRoleGateway;
import com.nidu.demo.user.model.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * 租户创建命令执行器
 *
 * @author auto
 */
@Component
@RequiredArgsConstructor
public class TenantAddCmdExe {

    private final TenantConvertor convertor;

    private final TenantDomainService domainService;

    private final TenantPackageDomainService packageDomainService;

    private final TenantGateway gateway;

    private final UserGateway userGateway;

    private final RoleGateway roleGateway;

    private final RoleMenuGateway roleMenuGateway;

    private final UserRoleGateway userRoleGateway;

    public SingleResponse<TenantCO> execute(TenantAddCmd cmd) {
        // 1. 转换为领域对象
        Tenant tenant = Tenant.create(cmd.getName(), cmd.getAdminName(), cmd.getAdminMobile(), cmd.getWebsite(),
                cmd.getPackageId(), cmd.getExpireTime(), cmd.getAccountCount(),
                cmd.getRemark(), cmd.getSortOrder());

        // 2. 检查租户名称是否重复
        domainService.validateDuplicate(tenant.getName(), tenant.getId());

        // 3. 检查套餐是否被禁用
        TenantPackage tenantPackage = packageDomainService.validateTenantPackage(tenant.getPackageId());

        Tenant save = this.createTenant(tenant, tenantPackage, cmd.getAdminUsername());
        // 4. 转换为DTO返回
        TenantCO tenantCO = convertor.toClientObject(save);
        return SingleResponse.of(tenantCO);
    }

    @Transactional
    private Tenant createTenant(Tenant tenant, TenantPackage tenantPackage, String username) {
        Tenant save = gateway.create(tenant);

        TenantUtils.execute(save.getId(), () -> {
            // 创建租户管理员
            User admin = User.create(username, Constants.DEFAULT_PASSWORD, tenant.getAdminName(), tenant.getAdminMobile(), null);
            admin = userGateway.create(admin);
            // 创建角色
            Role role = Role.create(RoleCodeEnum.TENANT_ADMIN.getName(), RoleCodeEnum.TENANT_ADMIN.getCode(), RoleTypeEnum.SYSTEM.getType(), DataScopeEnum.ALL.getValue(), new HashSet<>(), Constants.DEFAULT_DESCRIPTION, 1);
            role = roleGateway.create(role);

            // 分配角色菜单
            roleMenuGateway.bindRoleMenus(role.getId(), tenantPackage.getMenuIds());
            // 创建用户角色
            userRoleGateway.bindUserRoles(admin.getId(), Collections.singleton(role.getId()));

            // 修改租户的管理员
            gateway.update(new Tenant().setId(tenant.getId()).setAdminId(admin.getId()));
        });

        return save;
    }
} 